home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / AETEGizmo ƒ / Semaphores.h < prev   
Text File  |  1998-06-21  |  6KB  |  147 lines

  1. #ifndef __SEMAPHORES__
  2. #define __SEMAPHORES__
  3.  
  4. #ifndef __THREADS__
  5. #include <Threads.h>
  6. #endif
  7.  
  8. //
  9. // Convenience routines
  10. //
  11. Boolean TimeExpired(unsigned long currentTime, unsigned long startTime, unsigned long stopTime);
  12. unsigned long CloserTick(unsigned long currentTime, unsigned long tick1, unsigned long tick2);
  13.  
  14. //========================================================================================
  15. // CLASS TThreadIDQueue
  16. //
  17. // Keep track of a queue of ThreadIDs
  18. //========================================================================================
  19.  
  20. class TThreadIDQueue
  21. {
  22. public:
  23.                     TThreadIDQueue() : fThreadCount(0), fReservedSpace(0), fThreadQueue(nil) {};
  24.                     ~TThreadIDQueue();
  25.     
  26.     OSErr            Enqueue(ThreadID threadToAdd);
  27.     ThreadID        Dequeue();
  28.     long            QueuedThreads() { return fThreadCount; }
  29.     
  30. private:
  31.     OSErr            InsureThreadQueueHasFreeSpace();
  32.  
  33.     long            fThreadCount;
  34.     long            fReservedSpace;
  35.     ThreadID**        fThreadQueue;
  36. };
  37.  
  38. enum
  39. {
  40.     kAnySemaphoreID = 0,
  41.     kNeverTimeoutSemaphore = 0x7FFFFFFF
  42. };
  43.  
  44. //========================================================================================
  45. // CLASS TSemaphore
  46. //
  47. // A semaphore consists of an owner thread and a list of blocked threads waiting to
  48. // become the owner.  When the semaphore is created, its resource count is specified
  49. // to be either 0 or 1 (larger numbers could be supported if a list of owning threads
  50. // was kept).
  51. //
  52. //  A thread requests to become the owner by calling Grab, and relinquishes
  53. // ownership by calling Release.  Non-threads can get ownership of the semaphore by 
  54. // calling SetAvailable(false); in this case even though fOwningThread will be nil, the 
  55. // semaphore will still work correctly because fAvailable is false and thus other threads
  56. // that grab the semaphore will block as they should.
  57. //
  58. // Semaphores are linked into a global list of all semaphores upon creation and removed
  59. // upon deletion.  Each semaphore has a unique ID (generated by a static method), and
  60. // the global list can be searched for a given ID (via another static method).
  61. //========================================================================================
  62.  
  63. class TSemaphore
  64. {
  65.     
  66. // --- Methods -------------------------------------------------------------------------------------
  67.  
  68. public:
  69.                             TSemaphore(long resourceCount = 1, long semaphoreID = kAnySemaphoreID);
  70. protected:
  71.     virtual                    ~TSemaphore();
  72.  
  73. public:
  74.     static    void            InitializeGlobals();
  75.     static    long            NewUniqueSemaphoreID();
  76.     static    TSemaphore*        FindSemaphore(long semaphoreID, Boolean createIfNotFound = false, long resourceCount = 1);
  77.     static    void            Idle();
  78.     static    void            ThreadDied(ThreadID threadID);
  79.     static    void            SetDefaultTimeout(long newDefault);
  80.     static    void            SetDefaultMaxWait(long newMaxWait);
  81.     
  82.             void            ReleaseReference();
  83.             void            Dispose();
  84.             long            SemaphoreID() const;
  85.  
  86.             OSErr            Grab(ThreadID threadID = kCurrentThreadID);
  87.             void            Release(ThreadID threadID = kCurrentThreadID);
  88.             ThreadID        ReleaseOneThread();
  89.             void            ReleaseAllThreads();
  90.             Boolean            Available() const;
  91.             void            SetAvailable(Boolean);
  92.             
  93.             void            ResetTimeoutTimer();
  94.             void            AddGracePeriod(long gracePeriod);
  95.             void            SetSemaphoreTimoutValue(long timeoutValue);
  96.             void            SetSemaphoreMaxWaitTime(long timeoutValue);
  97.             long            SemaphoreTimoutValue() { return fSemaphoreTimeoutValue; }
  98.             long            SemaphoreMaxWaitTime() { return fSemaphoreMaxWaitTime; }
  99.             
  100.             unsigned long    TimeoutTick();
  101.             Boolean            CheckIfTimerExpired(unsigned long currentTime);
  102.             void            SemaphoreTimedOut();
  103.             
  104. protected:
  105.             void            RemoveFromGlobalSemaphoreList();
  106.             
  107. // --- Fields -------------------------------------------------------------------------------------
  108.  
  109. private:
  110.     static    TSemaphore*        gFirstSemaphore;            // Pointer to the first semaphore in the global list of all semaphores
  111.     static    long            gSemaphoreIDSequence;        // The next available semaphore ID (used for assigning unique IDs)
  112.     static    long            gSemaphoreDefaultTimeout;    // Default time to wait before timing out
  113.     static    long            gSemaphoreDefaultMaxWait;    // Default maximum time to wait (exclusive of timer resets)
  114.     static    unsigned long    gLastTimeoutTest;            // The last tick that we looked for timed-out semaphores
  115.     static    unsigned long    gLastIdleTick;                // The last tick we got some idle time
  116.     static    unsigned long    gNextTimeoutTest;            // Next tick to look for semaphores that have timed out
  117.     
  118.             TSemaphore*        fNextSemaphore;                // Previous semaphore in the global list of all semaphores
  119.             TSemaphore*        fPreviousSemaphore;            // Next semaphore in the global list of all semaphores
  120.     
  121.             ThreadID        fOwnerThread;                // The thread that currently owns this semaphore
  122.             TThreadIDQueue    fBlockedThreads;            // Queue of threads blocked on this semaphore
  123.  
  124.             long            fResourceCount;                // The number of threads that may own this semaphore (0 or 1)
  125.             long            fSemaphoreID;                // The ID (usually unique) for this semaphore
  126.             long            fOwnerCount;                // The number of threads that currently own the semaphore (<= fResourceCount)
  127.             Boolean            fDisposed;                    // True if someone disposed this semaphore
  128.             long            fReferenceCount;            // Count of blocked threads, to keep semaphore around after "deletion"
  129.             OSErr            fFailOnWakeup;                // If set, all threads fail with this error when they wake up
  130.             
  131.             unsigned long    fBlockStartTick;            // TickCount at which first thread blocked on this semaphore
  132.             unsigned long    fTimeoutTick;                // The tick at which the semaphore will time out if timer
  133.                                                         // is not recet
  134.             long            fSemaphoreTimeoutValue;        // How long to wait after every timer reset
  135.             long            fSemaphoreMaxWaitTime;        // The maximum number of ticks to wait before ignoring timer
  136.                                                         // resets and just time out
  137. };
  138.  
  139. inline        void            TSemaphore::SetDefaultTimeout(long newDefault)    { gSemaphoreDefaultTimeout = newDefault; }
  140. inline        void            TSemaphore::SetDefaultMaxWait(long newMaxWait)    { gSemaphoreDefaultMaxWait = newMaxWait; }
  141. inline        unsigned long    TSemaphore::TimeoutTick()                        { return fTimeoutTick; }
  142.  
  143. inline        long            TSemaphore::SemaphoreID() const        { return fSemaphoreID;     }
  144.  
  145.  
  146. #endif
  147.